package com.zareal.ymcc.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.zareal.ymcc.domain.KillActivity;
import com.zareal.ymcc.domain.KillCourse;
import com.zareal.ymcc.enums.GlobalErrorCode;
import com.zareal.ymcc.mapper.KillActivityMapper;
import com.zareal.ymcc.service.IKillActivityService;
import com.zareal.ymcc.service.IKillCourseService;
import com.zareal.ymcc.util.AssertUtil;
import org.redisson.api.RSemaphore;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author Wilson
 * @since 2022-10-20
 */
@Service
public class KillActivityServiceImpl extends ServiceImpl<KillActivityMapper, KillActivity> implements IKillActivityService {
    @Autowired
    private IKillCourseService killCourseService;

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RedissonClient redissonClient;
    @Override
    public boolean insert(KillActivity entity) {
        entity.setTimeStr(entity.getBeginTime().toString());
        entity.setPublishTime(entity.getBeginTime());
        entity.setPublishStatus(KillActivity.WAIT_PUBLISH);
        return super.insert(entity);
    }
    @Override
    @Transactional
    public void getActivityOnline(Long id) {
        //1.判断活动是否存在
        KillActivity killActivity = selectById(id);
        AssertUtil.isNotNull(killActivity, GlobalErrorCode.ACTIVITY_IS_NULL);
        // 2.判断活动是否上架
        boolean boo = killActivity.getPublishStatus() == KillActivity.WAIT_PUBLISH;
        AssertUtil.isTrue(boo,GlobalErrorCode.ERROR);
        // 3.判断活动发布时间不能在当前时间之前
        Date beginTime = killActivity.getBeginTime();
        Date date = new Date();
        boolean timeBoo = beginTime.after(date);
        AssertUtil.isTrue(timeBoo,GlobalErrorCode.ACTIVITYTIME_ALREADY_PASS);
        // 4.判断该活动有没有秒杀课程存在
        List<KillCourse> killCourses =  selectKillCourseByActivetyId(id);
        AssertUtil.isTrue(killCourses.size() > 0,GlobalErrorCode.KILLCOURSE_IS_NULL);
        // 设置课程信号量
        killCourses.forEach(killCourse -> {
            // 设置信号量
            RSemaphore semaphore = redissonClient.getSemaphore(id + ":" + killCourse.getId());
            boolean trySetPermits = semaphore.trySetPermits(killCourse.getKillCount());

            if (trySetPermits){
                // 2.放入到Redis中 // hash结构中有个方法：keys("activity:")
//                map<id,map<courseId,value>>
                // 此处必须要求两个Key为string，否则报错
                redisTemplate.opsForHash().put(
                        "activityId:" + id,
                        killCourse.getId().toString(),
                        killCourse
                );
            }
            // 3.修改状态，时间
            killCourse.setPublishStatus(KillActivity.PUBLISHING);
            killCourse.setPublishTime(new Date());
            killCourseService.updateById(killCourse);
        });

        // 修改秒杀活动状态，发布时间
        killActivity.setPublishStatus(KillActivity.PUBLISHING);
        killActivity.setPublishTime(new Date());
        updateById(killActivity);
    }

    private List<KillCourse> selectKillCourseByActivetyId(Long id) {
        Wrapper<KillCourse> wrapper = new EntityWrapper<>();
        wrapper.eq("activity_id",id);
        return killCourseService.selectList(wrapper);
    }
}
